home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / getpwent.c < prev    next >
C/C++ Source or Header  |  1990-11-27  |  7KB  |  306 lines

  1. /*
  2.  * Copyright (c) 1988 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #if defined(LIBC_SCCS) && !defined(lint)
  19. static char sccsid[] = "@(#)getpwent.c    5.9 (Berkeley) 4/1/89";
  20. #endif /* LIBC_SCCS and not lint */
  21.  
  22. #include <sys/types.h>
  23. #include <sys/file.h>
  24. #include <stdio.h>
  25. #include <pwd.h>
  26. #include <ndbm.h>
  27.  
  28. static DBM *_pw_db;
  29. static FILE *_pw_fp;
  30. static struct passwd _pw_passwd;
  31. static int _pw_rewind = 1, _pw_stayopen;
  32. static char _pw_flag, *_pw_file = _PATH_PASSWD;
  33. static int _pw_old = 0;        /* 1 indicates old passwd file format. */
  34.  
  35. static start_pw(), scanpw(), fetch_pw(), getpw();
  36.  
  37. #define    MAXLINELENGTH    1024
  38. static char line[MAXLINELENGTH];
  39.  
  40. struct passwd *
  41. getpwent()
  42. {
  43.     datum key;
  44.     int rval;
  45.  
  46.     if (!_pw_db && !_pw_fp && !start_pw())
  47.         return((struct passwd *)NULL);
  48.     do {
  49.         if (_pw_db) {
  50.             key.dptr = NULL;
  51.             rval = fetch_pw(key);
  52.         } else /* _pw_fp */
  53.             rval = scanpw();
  54.     } while (rval && (_pw_db && _pw_flag != _PW_KEYBYNAME));
  55.     if (rval)
  56.         getpw();
  57.     return(rval ? &_pw_passwd : (struct passwd *)NULL);
  58. }
  59.  
  60. struct passwd *
  61. getpwnam(nam)
  62.     char *nam;
  63. {
  64.     int rval;
  65.  
  66.     if (!start_pw())
  67.         return((struct passwd *)NULL);
  68.     if (_pw_db) {
  69.         datum key;
  70.  
  71.         key.dptr = nam;
  72.         key.dsize = strlen(nam);
  73.         rval = fetch_pw(key);
  74.     } else /* _pw_fp */
  75.         for (rval = 0; scanpw();)
  76.             if (!strcmp(nam, _pw_passwd.pw_name)) {
  77.                 rval = 1;
  78.                 break;
  79.             }
  80.     if (!_pw_stayopen)
  81.         endpwent();
  82.     if (rval)
  83.         getpw();
  84.     return(rval ? &_pw_passwd : (struct passwd *)NULL);
  85. }
  86.  
  87. struct passwd *
  88. getpwuid(uid)
  89.     int uid;
  90. {
  91.     int rval;
  92.  
  93.     if (!start_pw())
  94.         return((struct passwd *)NULL);
  95.     if (_pw_db) {
  96.         datum key;
  97.  
  98.         key.dptr = (char *)&uid;
  99.         key.dsize = sizeof(uid);
  100.         rval = fetch_pw(key);
  101.     } else /* _pw_fp */
  102.         for (rval = 0; scanpw();)
  103.             if (_pw_passwd.pw_uid == uid) {
  104.                 rval = 1;
  105.                 break;
  106.             }
  107.     if (!_pw_stayopen)
  108.         endpwent();
  109.     if (rval)
  110.         getpw();
  111.     return(rval ? &_pw_passwd : (struct passwd *)NULL);
  112. }
  113.  
  114. static
  115. start_pw()
  116. {
  117.     char *p;
  118.  
  119.     if (_pw_db) {
  120.         _pw_rewind = 1;
  121.         return(1);
  122.     }
  123.     if (_pw_fp) {
  124.         rewind(_pw_fp);
  125.         return(1);
  126.     }
  127.     if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))
  128.         return(1);
  129.     /*
  130.      * special case; if it's the official password file, look in
  131.      * the master password file, otherwise, look in the file itself.
  132.      * But, only look in the master file if we're root.
  133.      */
  134.     if (!strcmp(_pw_file, _PATH_PASSWD)) {
  135.         if (geteuid()) {
  136.         p = _pw_file;
  137.         _pw_old = 1;
  138.         } else {
  139.         p = _PATH_MASTERPASSWD;
  140.         }
  141.     } else {
  142.         p = _pw_file;
  143.     }
  144.     if (_pw_fp = fopen(p, "r"))
  145.         return(1);
  146.     return(0);
  147. }
  148.  
  149. setpwent()
  150. {
  151.     return(setpassent(0));
  152. }
  153.  
  154. setpassent(stayopen)
  155.     int stayopen;
  156. {
  157.     if (!start_pw())
  158.         return(0);
  159.     _pw_stayopen = stayopen;
  160.     return(1);
  161. }
  162.  
  163. void
  164. endpwent()
  165. {
  166.     if (_pw_db) {
  167.         dbm_close(_pw_db);
  168.         _pw_db = (DBM *)NULL;
  169.     } else if (_pw_fp) {
  170.         (void)fclose(_pw_fp);
  171.         _pw_fp = (FILE *)NULL;
  172.     }
  173. }
  174.  
  175. void
  176. setpwfile(file)
  177.     char *file;
  178. {
  179.     _pw_file = file;
  180. }
  181.  
  182. static
  183. scanpw()
  184. {
  185.     register char *cp;
  186.     long atol();
  187.     char *fgets(), *strsep(), *index();
  188.  
  189.     for (;;) {
  190.         if (!(fgets(line, sizeof(line), _pw_fp)))
  191.             return(0);
  192.         /* skip lines that are too big */
  193.         if (!index(line, '\n')) {
  194.             int ch;
  195.  
  196.             while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
  197.                 ;
  198.             continue;
  199.         }
  200.         _pw_passwd.pw_name = strsep(line, ":\n");
  201.         _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n");
  202.         if (!(cp = strsep((char *)NULL, ":\n")))
  203.             continue;
  204.         _pw_passwd.pw_uid = atoi(cp);
  205.         if (!(cp = strsep((char *)NULL, ":\n")))
  206.             continue;
  207.         _pw_passwd.pw_gid = atoi(cp);
  208.         if (_pw_old) {
  209.             _pw_passwd.pw_class = "";
  210.             _pw_passwd.pw_change = 0;
  211.             _pw_passwd.pw_expire = 0;
  212.         } else {
  213.             _pw_passwd.pw_class = strsep((char *)NULL, ":\n");
  214.             if (!(cp = strsep((char *)NULL, ":\n")))
  215.                 continue;
  216.             _pw_passwd.pw_change = atol(cp);
  217.             if (!(cp = strsep((char *)NULL, ":\n")))
  218.             continue;
  219.             _pw_passwd.pw_expire = atol(cp);
  220.         }
  221.         _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n");
  222.         _pw_passwd.pw_dir = strsep((char *)NULL, ":\n");
  223.         _pw_passwd.pw_shell = strsep((char *)NULL, ":\n");
  224.         if (!_pw_passwd.pw_shell)
  225.             continue;
  226.         return(1);
  227.     }
  228.     /* NOTREACHED */
  229. }
  230.  
  231. static
  232. fetch_pw(key)
  233.     datum key;
  234. {
  235.     register char *p, *t;
  236.  
  237.     /*
  238.      * the .dir file is LOCK_EX locked by programs that are
  239.      * renaming the various password files.
  240.      */
  241.     if (flock(dbm_dirfno(_pw_db), LOCK_SH))
  242.         return(0);
  243.     if (!key.dptr)
  244.         if (_pw_rewind) {
  245.             _pw_rewind = 0;
  246.             key = dbm_firstkey(_pw_db);
  247.         } else
  248.             key = dbm_nextkey(_pw_db);
  249.     if (key.dptr)
  250.         key = dbm_fetch(_pw_db, key);
  251.     (void)flock(dbm_dirfno(_pw_db), LOCK_UN);
  252.     if (!(p = key.dptr))
  253.         return(0);
  254.     t = line;
  255. #define    EXPAND(e)    e = t; while (*t++ = *p++);
  256.     EXPAND(_pw_passwd.pw_name);
  257.     EXPAND(_pw_passwd.pw_passwd);
  258.     bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
  259.     p += sizeof(int);
  260.     bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
  261.     p += sizeof(int);
  262.     bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
  263.     p += sizeof(time_t);
  264.     EXPAND(_pw_passwd.pw_class);
  265.     EXPAND(_pw_passwd.pw_gecos);
  266.     EXPAND(_pw_passwd.pw_dir);
  267.     EXPAND(_pw_passwd.pw_shell);
  268.     bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
  269.     p += sizeof(time_t);
  270.     _pw_flag = *p;
  271.     return(1);
  272. }
  273.  
  274. static
  275. getpw()
  276. {
  277.     static char pwbuf[50];
  278.     off_t lseek();
  279.     long pos, atol();
  280.     int fd, n;
  281.     char *p;
  282.  
  283.     if (!_pw_db || geteuid())
  284.         return;
  285.     /*
  286.      * special case; if it's the official password file, look in
  287.      * the master password file, otherwise, look in the file itself.
  288.      */
  289.     p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
  290.     if ((fd = open(p, O_RDONLY, 0)) < 0)
  291.         return;
  292.     pos = atol(_pw_passwd.pw_passwd);
  293.     if (lseek(fd, pos, L_SET) != pos)
  294.         goto bad;
  295.     if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0)
  296.         goto bad;
  297.     pwbuf[n] = '\0';
  298.     for (p = pwbuf; *p; ++p)
  299.         if (*p == ':') {
  300.             *p = '\0';
  301.             _pw_passwd.pw_passwd = pwbuf;
  302.             break;
  303.         }
  304. bad:    (void)close(fd);
  305. }
  306.